﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
using System.Windows;
using System.Collections.Concurrent;
using System.Net;
using System.Security.Authentication;

namespace TCommon
{
   public class WSocketClient
    {
        private ConcurrentQueue<string> sendQueue = new ConcurrentQueue<string>();
        private bool threadNeedClose = false;

        #region 向外传递数据事件
        public event Action<string> MessageReceived;
        #endregion                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

        WebSocketSharp.WebSocket Socket;

        /// <summary>
        /// 检查重连线程
        /// </summary>
        Thread _thread;
        bool _isRunning = true;
        /// <summary>
        /// WebSocket连接地址
        /// </summary>
        public string ServerPath { get; set; }

        public WSocketClient(string url)
        {
            this._thread = new Thread(new ThreadStart(DoSend));
            this._thread.IsBackground = true;
            this._thread.Start();
            ServerPath = url;
        }
        #region "web socket "
        public void Stop() {
            threadNeedClose = true;
            this._thread.Abort();
            this.Socket.Close();
        }


        private void DoSend() {
            bool needRetry = false;
            int retryCount = 0;
            string message = string.Empty;
            while (true) {
                try
                {
                    if (threadNeedClose)
                        return;

                    if (this.Socket == null || this.Socket.ReadyState == WebSocketState.Closed
                       || this.Socket.ReadyState == WebSocketState.Closing)
                    {
                        Connect();
                    }

                    if (!needRetry)
                    {
                        sendQueue.TryDequeue(out message);
                    }

                    if (!string.IsNullOrEmpty(message))
                    {
                        if (this.Socket.ReadyState == WebSocketState.Open)
                        {
                            this.Socket.Send(message);
                        }
                        else
                        {
                            throw new Exception("websocket connection is not open");
                        }
                    }

                    needRetry = false;
                    retryCount = 0;
                }
                catch (Exception ex)
                {
                    if (needRetry)
                    {
                        if (retryCount < 5)
                        {
                            retryCount++;
                        }
                        else
                        {

                            needRetry = false;
                        }
                    }
                    else
                    {
                        needRetry = true;
                    }

                    Thread.Sleep(1000);
                }

                Thread.Sleep(50);
            }
        }
        #endregion
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="Message"></param>
        public void SendMessage(string Message) 
        {
            sendQueue.Enqueue(Message);
        }

        private void Connect() {
            if (this.Socket == null)
            {
                try
                {
                    if (this.Socket != null)
                    {
                        this.Socket.OnMessage -= Socket_OnMessage;
                        this.Socket?.Close();
                    }
                }
                catch (Exception)
                {
                    //Nothing to do
                }

                this.Socket = new WebSocketSharp.WebSocket(ServerPath);
                this.Socket.OnOpen += Socket_OnOpen;
                this.Socket.OnClose += Socket_OnClose;
                this.Socket.OnError += Socket_OnError;
                this.Socket.OnMessage += Socket_OnMessage;
                this.Socket.SslConfiguration.EnabledSslProtocols = (SslProtocols)3072;
                Socket.SslConfiguration.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                {
                    return true; // If the server certificate is valid.
                };
                this.Socket.Connect();
            }
        }

        private void Socket_OnMessage(object sender, MessageEventArgs e)
        {
            MessageReceived?.Invoke(e.Data);
        }

        private void Socket_OnError(object sender, ErrorEventArgs e)
        {
            
        }

        private void Socket_OnClose(object sender, CloseEventArgs e)
        {
            
        }

        private void Socket_OnOpen(object sender, EventArgs e)
        {
            
        }
    }
}
